package com.company.beauty.dao;

import com.alibaba.fastjson.JSONObject;
import com.company.beauty.constants.BaseModelConstants;
import com.company.beauty.domain.mapper.BaseMapper;
import com.company.nuwa.common.enumration.DeleteEnum;
import com.company.nuwa.common.enumration.EnableEnum;
import com.company.nuwa.common.utils.JsonUtils;
import com.company.nuwa.common.utils.ZkPlatformUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import java.lang.reflect.Field;
import java.util.*;

/**
 * <p>基本dao</p>
 *
 * @author Lionel Lee
 * @version 1.0: BaseDao.java
 * @date 2020/8/19 10:48
 */
@Slf4j
public abstract class AbstractBaseDao<T, E extends BaseMapper> {

    @Autowired
    public E mapper;

    @Value("${common.dao.fillField.enabled:false}")
    private boolean fillField;

    @Value("${common.dao.setPlatformId.enabled:true}")
    private boolean setPlatformId;

    public String getTableName() {
        return "";
    }

    /**
     * 保存记录
     *
     * @param record 记录
     * @return int
     */
    public int insert(T record) {
        fillField(true, record);
        return mapper.insertSelective(record);
    }

    /**
     * 更新记录
     *
     * @param record 记录
     * @return int
     */
    public int update(T record) {
        fillField(false, record);
        return mapper.updateByPrimaryKeySelective(record);
    }

    private void fillField(boolean isCreate, T record) {
        // 平台id
        if (setPlatformId) {
            setFillField(
                    record,
                    BaseModelConstants.PLATFORM_ID,
                    Objects.nonNull(ZkPlatformUtils.getPlatformId()) ? ZkPlatformUtils.getPlatformId() : 0
            );
        }
        // TODO:自动填充基础字段值
        fillBasicField(isCreate, record);
    }

    private void fillBasicField(boolean isCreate, T record) {
        if (!fillField) {
            log.info("Auto Fill Field disabled");
            return;
        }
        log.info("Auto Fill Field enabled");
        log.info("[开始填充字段值,record:{}]", JsonUtils.objectToJson(record));
        if (isCreate) {
            // 创建人
            setFillField(record, BaseModelConstants.CREATE_BY, "0");
            // 创建时间
            setFillField(record, BaseModelConstants.CREATE_TIME, new Date());
            // 是否删除
            setFillField(record, BaseModelConstants.IS_DEL, DeleteEnum.NOT_DELETED.getCode());
            // 版本号
            setFillField(record, BaseModelConstants.VERSION, "1");
            // 是否启用
            setFillField(record, BaseModelConstants.IS_ENABLE, EnableEnum.ENABLE.getCode());
        }
        // 修改人
        setFillField(record, BaseModelConstants.UPDATE_BY, "0");
        // 修改时间
        setFillField(record, BaseModelConstants.UPDATE_TIME, new Date());
        log.info("[结束填充字段值,record:{}]", JsonUtils.objectToJson(record));
    }

    private <R extends Object> void setFillField(T record, String fieldName, R value) {
        log.info("[开始填充字段值,{}:{}]", fieldName, value);
        try {
            if (record instanceof JSONObject jsonObject) {
                log.info("[开始填充字段值,{}:{}, oldValue:{}, isNull:{}]", fieldName, value, jsonObject.get(fieldName), Objects.isNull(jsonObject.get(fieldName)));
                if (Objects.isNull(jsonObject.get(fieldName))) {
                    jsonObject.put(fieldName, value);
                    log.info("[开始填充字段值,{}:{}, success]", fieldName, value);
                }
            } else {
                Optional<Field> createByField = Arrays.stream(record.getClass().getDeclaredFields())
                        .filter(field -> field.getName().equals(fieldName)).findFirst();
                if (createByField.isPresent()) {
                    Field field = createByField.get();
                    field.setAccessible(true);

                    if (Objects.isNull(field.get(record))) {
                        if (Objects.equals("Integer", field.getType().getSimpleName())) {
                            field.set(record, Integer.parseInt(String.valueOf(value)));
                        } else if (Objects.equals("Long", field.getType().getSimpleName())) {
                            field.set(record, Long.parseLong(String.valueOf(value)));
                        } else {
                            field.set(record, value);
                        }
                        log.info("[开始填充字段值,{}:{}, success]", fieldName, value);
                    }
                }
            }
        } catch (Exception e) {
            log.error("Failed to fill Field:{},error:{}", fieldName, ExceptionUtils.getStackTrace(e));
        }
    }

    /**
     * 查询记录根据主键
     *
     * @param id 记录
     * @return int
     */
    public T selectById(String id) {
        return (T) mapper.selectByPrimaryKey(Long.valueOf(id));
    }

    /**
     * 查询记录根据主键
     *
     * @param id 记录
     * @return int
     */
    public T selectById(Long id) {
        return (T) mapper.selectByPrimaryKey(id);
    }

    /**
     * 批量插入
     *
     * @param list 记录
     * @return int
     */
    public int batchInsert(List<T> list) {
        for (T record : list) {
            fillField(true, record);
        }
        return mapper.batchInsert(list);
    }

    /**
     * 批量更新
     *
     * @param list 记录
     * @return int
     */
    public int batchUpdate(List<T> list) {
        for (T record : list) {
            fillField(false, record);
        }
        return mapper.batchUpdate(list);
    }

    /**
     * 批量更新
     *
     * @param list 记录
     * @return int
     */
    public int batchReplace(List<T> list) {
        for (T record : list) {
            fillField(true, record);
        }
        return mapper.batchReplace(list);
    }

    /**
     * 查询记录根据主键
     *
     * @param id 记录
     * @return int
     */
    public int deleteById(Long id) {
        return mapper.deleteByPrimaryKey(id);
    }

    /**
     * 批量动态插入
     *
     * @param list 记录
     * @return int
     */
    public void batchInsertSelective(List<T> list) {
        for (T record : list) {
            fillField(true, record);
        }
        mapper.batchInsertSelective(list);
    }
}
